<template>
      <video v-if="hasData" :id='"A"+video.uid + id'
             class=""
             autoplay
             muted
             ref="videoPlayer"
      ></video>
  <div v-else-if="wsError" :id='"A"+video.uid + id' class="bg-black text-white text-center relative">
        <div class="absolute top-0 left-0 right-0 bottom-0 flex items-center justify-center">
          视频加载失败，请检查网络或设备是否正常
        </div>
  </div>
  <div v-else v-loading="!hasData" :id='"A"+video.uid + id'
       element-loading-background="rgba(0, 0, 0, 0)"
       class="relative bg-black">

  </div>
</template>
<script>
import JMuxer from 'jmuxer';
import {postStartPreview} from "@/api/api2";
import {forceKeyFrame, getvideoparam} from "@/api/api";
import workerScript from '@/utils/heart.js';
let mediaRecorder; // MediaRecorder对象

export default {
  props: {
    id: {
      default: '0',
    }
  },
  data() {
    return {
      hasData: false,
      wsError: false,

      video: {
        url: "ws://192.168.2.168:8000",
        index: 0,
        deviceId: 0,
        sessionId: 0,
        name: '',
        itemCode: '',
        fps: 30,
        uid:'0'
      },
      worker: null,// 心跳定时器worker对象
      url:'',
      videoGo: true,
      videoData: [], // 视频流数据
      videoUrl: "", // 录制的视频地址
      imgUrl: "", // 截图地址
      jmuxer: null,//转换器对象
      websock: null,//ws对象
      videoL: "",
      sendHeart: {
        "cmd": "heart",
      },
      //心跳定时器
      time: '',
      videos: '',
      agentData: '',
    }
  },
  // watch: {
  //   'video.url': {
  //     handler(newVal, oldVal) {
  //       console.log('url属性修改');
  //       console.log(newVal,oldVal);
  //       if(newVal != ""){
  //         this.checkWS();
  //       }
  //     },
  //   }
  // },
  mounted() {
    document.addEventListener('fullscreenchange', this.onFullscreenChange);
    this.videos =  document.getElementById("A" + this.video.uid + this.id)
    this.checkWS();
  },
  methods: {
    playVideo() {
      this.videos.currentTime = this.videos.currentTime + 9999;
    },

    // 录像
    videoShow(i) {
      console.log("视频录像")
      if (this.videoGo != true) {
        this.videoGo = true
        mediaRecorder.stop()
        this.showCapture()
      } else {
        this.videoGo = false
        this.onloadedmetadata()
        // 500ms 后执行第二个方法
        setTimeout(() => {
          this.$message.success("开始录制")
          mediaRecorder.start()
        }, 500)

      }
    },

    /***************流媒体数据 *****************************************************/
    checkWS() {
        getvideoparam().then(res => {
          this.video.fps = res.data.frameRate
        })
        postStartPreview().then(res => {
          this.video.url = res.data.ws_addr
          if (this.video.url == "") {
          } else {
            this.videoData=[]
            this.getVideoData()
          }
        }).catch(error => {
          console.error("获取视频地址失败", error);
          this.wsError = true;
        });
    },
    //请求流媒体数据
    getVideoData() {
      console.log("connecting to " + this.video.url)
      this.agentData = { cmd: 'verifyclient', sessionid: this.video.sessionId };
      this.websock = new WebSocket(this.video.url);
      this.websock.onopen = this.websocketOpen;
      this.websock.onmessage = this.websocketonmessage;
      this.websock.onclose = this.websocketclose;
      this.websock.onerror = this.websocketerror;
      this.websock.binaryType = 'arraybuffer';
    },
    websocketOpen() {
      this.hasData = true;
      this.$nextTick(() => {
        this.jmuxer = new JMuxer({
          node: "A" + this.video.uid + this.id,
          mode: 'video',
          fps: this.video.fps,
          flushingTime: 0,
          readFpsFromTrack: true,
          clearBuffer: true,
          codec: 'h264'
        });
      });
      let encoder = new TextEncoder();
      console.log('WebSocket connected.');
      forceKeyFrame()


      let uint8array = encoder.encode(JSON.stringify(this.sendHeart)); // 将字符串编码为 Uint8Array 类型的二进制数据


      // // 创建 Blob 和 Blob URL
      const workerBlob = new Blob([workerScript], { type: 'application/javascript' });
      const workerUrl = URL.createObjectURL(workerBlob);

      // // 创建 Web Worker 实例
      this.worker = new Worker(workerUrl);
      //
      // // 定义接收来自 Web Worker 消息的处理器
      this.worker.onmessage = (event) => {
        if (event.data === 'heartbeat') {
          this.websock.send(uint8array); // 这里的 this 现在正确地指向 Vue 组件实例
          console.log("心跳");
        }
      };
      // // 启动 Web Worker 的心跳逻辑
      this.worker.postMessage('start');
    },
    websocketonmessage(e) {
      if (this.jmuxer) {
        this.jmuxer.feed({
          video: new Uint8Array(e.data)
        });
      }
    },
    websocketerror(e) {
      console.error('WebSocket error.');
      this.wsError = true;
    },
    websocketclose(e) {  //关闭
      console.log(`WebSocket closed.`);
      this.websock.onmessage = null;
      this.websock.onclose = null;
      this.websock.onerror = null;
      this.websock = null;
      clearInterval(this.timer)
      this.worker.postMessage('stop');
      this.worker.terminate();
    },
    /***************流媒体数据结束 *****************************************************/
    // video元数据加载后触发
    onloadedmetadata() {
      this.videoL = document.querySelector("#A" + this.video.uid + this.id)
      const that = this
      mediaRecorder = new MediaRecorder(this.videoL.captureStream(25), {videoBitsPerSecond: 100000,})  // 生成速率25的MediaRecorder对象
      const _this = this
      _this.videoData = []
      mediaRecorder.ondataavailable = function (e) {
        _this.videoData.push(e.data) // 添加视频流
      }
    },
    // 截图
    handleScreenshot() {
      this.videoL = document.querySelector("#A" + this.video.uid + this.id) // 获取video节点
      let canvas = document.createElement("canvas") // 创建canvas节点
      let w = 640
      let h = 480
      canvas.width = w
      canvas.height = h // 设置宽高
      const ctx = canvas.getContext("2d")
      ctx.drawImage(this.videoL, 0, 0, w, h) // video写入到canvas
      this.imgUrl = canvas.toDataURL("image/png") // 生成截图地址
      const link = document.createElement("a");
      link.href = this.imgUrl;
      link.download = this.video.name + new Date().toLocaleString()+".png"; // 下载时文件名为video.mp4
      document.body.appendChild(link);
      link.click();
    },
    // 返回视频地址
    showCapture() {
      return new Promise((resolve) => {
        setTimeout(() => {
          let blob = new Blob(this.videoData, {
            type: "video/mp4",
          });
          // 将 Blob 对象转换为 File 对象
          const file = new File(this.videoData, "video.mp4", {type: "video/mp4"});
          // this.uploadFile(file)
          this.videoUrl = window.URL.createObjectURL(blob)
          const link = document.createElement("a");
          link.href = this.videoUrl;
          link.download = new Date().toLocaleString() + ".mp4"; // 下载时文件名为video.mp4
          document.body.appendChild(link);
          link.click();
          // 清理URL对象
          URL.revokeObjectURL(this.videoUrl);
          resolve()
        })
      })
    },
    closeWs() {
      console.log("closeWs：关闭" + this.video.index);
      // this.$emit('close');
      this.isShow = false
      this.jmuxer=''
      clearInterval(this.timer)
      this.websock.close();
    },
    onFullscreenChange() {
      if (!document.fullscreenElement) {  // 如果没有元素处于全屏模式，说明用户已退出全屏
        this.$emit('exitFullScreen');  // 触发一个自定义事件来通知父组件
      }
    },
    full(i) {
      this.$emit("fullScreen");
      this.videos.requestFullscreen()
    }
  },
  beforeDestroy() {
    console.log("videoplayer beforeDestroy");
    if (this.websock != '' && this.websock != null) {

      this.websock.send("close")
      console.log("ws close--");
      this.websock.close();
    }

  },
  computed: {
  },
}
</script>
<style scoped>
@keyframes spin-ease {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

/* 创建一个自定义类来应用这个动画 */
.loader-ease {
  /*
    动画名称: spin-ease
    持续时间: 1.5秒
    速度曲线: cubic-bezier(...) 这是一个带回弹效果的缓动，非常生动
               你也可以用 'ease-in-out' 获得一个更平滑的效果
    循环次数: infinite (无限)
  */
  animation: spin-ease 1.5s cubic-bezier(0.68, -0.55, 0.27, 1.55) infinite;
}
</style>
